package com.lemon.reggie.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lemon.reggie.common.BusinessException;
import com.lemon.reggie.pojo.dto.AgainOrderDTO;
import com.lemon.reggie.pojo.dto.GiveOrderDTO;
import com.lemon.reggie.pojo.dto.SubmitOrderDTO;
import com.lemon.reggie.pojo.entity.*;
import com.lemon.reggie.mapper.OrdersMapper;
import com.lemon.reggie.pojo.vo.OrderDetailVO;
import com.lemon.reggie.pojo.vo.OrderPageVO;
import com.lemon.reggie.pojo.vo.OrderVO;
import com.lemon.reggie.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lemon.reggie.utils.BaseContextUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author Lemon
 * @since 2022-05-23
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Resource
    private ShoppingCartService shoppingCartService;
    @Resource
    private UserService userService;
    @Resource
    private AddressBookService addressBookService;
    @Resource
    private OrderDetailService orderDetailService;

    /**
     * 用户下单
     * @param submitOrderDTO
     * @return void
     * @author Guannankun
     * @since 2022/8/29
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void submitOrder(SubmitOrderDTO submitOrderDTO) {
        LambdaQueryWrapper<ShoppingCart> wrapper = new LambdaQueryWrapper<ShoppingCart>()
                .eq(ShoppingCart::getUserId, BaseContextUtil.getCurrentId());
        List<ShoppingCart> cartList = shoppingCartService.list(wrapper);

        if (CollUtil.isEmpty(cartList)) {
            throw new BusinessException("购物车为空，不能下单！");
        }

        User user = this.getUser(BaseContextUtil.getCurrentId());
        AddressBook addressBook = this.getAddressBook(submitOrderDTO.getAddressBookId());
        //获取订单号
        long orderId = IdWorker.getId();
        //计算总价，原子操作，并发下保证数据一致   初始化总价为0
        AtomicInteger amount = new AtomicInteger(0);

        List<OrderDetail> orderDetailList = cartList.stream().map(shoppingCart -> {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setName(shoppingCart.getName());
            orderDetail.setImage(shoppingCart.getImage());
            orderDetail.setOrderId(orderId);
            orderDetail.setDishId(shoppingCart.getDishId());
            orderDetail.setSetmealId(shoppingCart.getSetmealId());
            orderDetail.setDishFlavor(shoppingCart.getDishFlavor());
            orderDetail.setNumber(shoppingCart.getNumber());
            orderDetail.setAmount(shoppingCart.getAmount());
            /*
                addAndGet 加后了再获取值，
                即 第一次 0 + 单价1 * 数量1
                  第二次  (单价1 * 数量1) + (单价2 * 数量2) ...
             */                                         //单价 * 数量
            amount.addAndGet(shoppingCart.getAmount().multiply(new BigDecimal(shoppingCart.getNumber())).intValue());
            return orderDetail;
        }).collect(Collectors.toList());
        orderDetailService.saveBatch(orderDetailList);

        Orders orders = new Orders();
        orders.setId(orderId);
        orders.setNumber(String.valueOf(orderId));
        orders.setStatus(2);
        orders.setUserId(BaseContextUtil.getCurrentId());
        orders.setAddressBookId(submitOrderDTO.getAddressBookId());
        orders.setOrderTime(LocalDateTime.now());
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setPayMethod(submitOrderDTO.getPayMethod());
        //总价
        orders.setAmount(new BigDecimal(amount.get()));
        orders.setRemark(submitOrderDTO.getRemark());
        orders.setPhone(Objects.nonNull(user) ? user.getPhone() : null);
        orders.setAddress(addressBook.getDetail());
        orders.setUserName(Objects.nonNull(user) ? user.getName() : null);
        orders.setConsignee(addressBook.getConsignee());
        this.save(orders);

        //删除购物车数据
        shoppingCartService.remove(wrapper);
    }

    /**
     * 用户订单详情分页
     * @param currentPage
     * @param pageSize
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.lemon.reggie.pojo.vo.OrderVO>
     * @author Guannankun
     * @since 2022/8/29
     */
    @Override
    public IPage<OrderVO> userOrderPage(Long currentPage, Long pageSize) {
        IPage<Orders> page = new Page<>(currentPage, pageSize);
        IPage<Orders> ordersPage = this.page(page, new LambdaQueryWrapper<Orders>().eq(Orders::getUserId, BaseContextUtil.getCurrentId()).orderByDesc(Orders::getCheckoutTime));

        List<Orders> records = ordersPage.getRecords();
        List<OrderVO> orderVOS = new ArrayList<>();
        if (CollUtil.isNotEmpty(records)) {
            orderVOS= records.stream().map(orders -> {
                OrderVO orderVO = new OrderVO();
                BeanUtil.copyProperties(orders, orderVO);
                orderVO.setOrderDetails(this.getOrderDetailVOS(orders.getId()));
                return orderVO;
            }).collect(Collectors.toList());
        }

        IPage<OrderVO> orderVOPage = new Page<>(currentPage, pageSize);
        BeanUtil.copyProperties(ordersPage, orderVOPage, "records");
        orderVOPage.setRecords(orderVOS);
        return orderVOPage;
    }

    /**
     * 再次下单
     * @param againOrderDTO
     * @return void
     * @author Guannankun
     * @since 2022/8/29
     */
    @Override
    public void againOrder(AgainOrderDTO againOrderDTO) {
        //1 订单
        Orders sourceOrder = this.getById(againOrderDTO.getId());
        if (Objects.isNull(sourceOrder)) {
            throw new BusinessException("当前订单不存在，无法再来一单！");
        }

        Orders nowOrder = new Orders();
        BeanUtil.copyProperties(sourceOrder, nowOrder,
                "id", "number", "status", "orderTime", "checkoutTime");
        long nowOrderId = IdWorker.getId();
        nowOrder.setId(nowOrderId);
        nowOrder.setStatus(2);
        nowOrder.setNumber(String.valueOf(nowOrderId));
        nowOrder.setOrderTime(LocalDateTime.now());
        nowOrder.setCheckoutTime(LocalDateTime.now());
        this.save(nowOrder);

        //2 订单详情
        List<OrderDetail> list = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, againOrderDTO.getId()));
        if (CollUtil.isNotEmpty(list)) {
            List<OrderDetail> nowList = list.stream().map(orderDetail -> {
                OrderDetail nowOrderDetail = new OrderDetail();
                BeanUtil.copyProperties(orderDetail, nowOrderDetail,
                        "id", "orderId");
                nowOrderDetail.setOrderId(nowOrderId);
                return nowOrderDetail;
            }).collect(Collectors.toList());
            orderDetailService.saveBatch(nowList);
        }
    }

    /**
     * 后台订单明细分页
     * @param currentPage
     * @param pageSize
     * @param number
     * @param beginTime
     * @param endTime
     * @return com.baomidou.mybatisplus.core.metadata.IPage<com.lemon.reggie.pojo.vo.OrderPageVO>
     * @author Guannankun
     * @since 2022/8/29
     */
    @Override
    public IPage<OrderPageVO> orderPage(Long currentPage, Long pageSize, String number,
                                        String beginTime, String endTime) {
        IPage<Orders> page = new Page<>(currentPage, pageSize);
        IPage<Orders> ordersPage = this.page(page, new LambdaQueryWrapper<Orders>()
                .like(StrUtil.isNotBlank(number), Orders::getId, number)
                .between(StrUtil.isNotBlank(beginTime) && StrUtil.isNotBlank(endTime),
                        Orders::getOrderTime, beginTime, endTime)
                .orderByDesc(Orders::getOrderTime));

        List<OrderPageVO> orderPageVOS = new ArrayList<>();
        List<Orders> records = ordersPage.getRecords();
        if (CollUtil.isNotEmpty(records)) {
            orderPageVOS = records.stream().map(orders -> {
                OrderPageVO orderPageVO = new OrderPageVO();
                BeanUtil.copyProperties(orders, orderPageVO);
                return orderPageVO;
            }).collect(Collectors.toList());
        }

        IPage<OrderPageVO> orderPageVOPage = new Page<>(currentPage, pageSize);
        BeanUtil.copyProperties(ordersPage, orderPageVOPage, "records");
        orderPageVOPage.setRecords(orderPageVOS);
        return orderPageVOPage;
    }

    /**
     * 派送订单
     * @param giveOrderDTO
     * @return void
     * @author Guannankun
     * @since 2022/8/29
     */
    @Override
    public void giveOrder(GiveOrderDTO giveOrderDTO) {
        Orders orders = this.getById(giveOrderDTO.getId());
        if (Objects.isNull(orders)) {
            throw new BusinessException("当前订单不存在！");
        }

        orders.setStatus(giveOrderDTO.getStatus());
        this.updateById(orders);
    }

    /**
     * 根据orderId获取订单详情
     * @param orderId
     * @return java.util.List<com.lemon.reggie.pojo.vo.OrderDetailVO>
     * @author Guannankun
     * @since 2022/8/29
     */
    private List<OrderDetailVO> getOrderDetailVOS(Long orderId) {
        List<OrderDetail> orderDetailList = orderDetailService.list(new LambdaQueryWrapper<OrderDetail>()
                .eq(OrderDetail::getOrderId, orderId));
        if (CollUtil.isNotEmpty(orderDetailList)) {
           return orderDetailList.stream().map(orderDetail -> OrderDetailVO.builder()
                    .orderId(orderDetail.getOrderId())
                    .name(orderDetail.getName())
                    .image(orderDetail.getImage())
                    .amount(orderDetail.getAmount())
                    .number(orderDetail.getNumber())
                    .dishId(orderDetail.getDishId())
                    .dishFlavor(orderDetail.getDishFlavor())
                    .setmealId(orderDetail.getSetmealId())
                    .build()).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 获取用户信息
     * @param userId
     * @return com.lemon.reggie.pojo.entity.User
     * @author Guannankun
     * @since 2022/8/29
     */
    private User getUser(Long userId) {
        User user = userService.getById(userId);
        return Objects.nonNull(user) ? user : null;
    }

    /**
     * 获取用户的默认地址
     * @param addressBookId
     * @return com.lemon.reggie.pojo.entity.AddressBook
     * @author Guannankun
     * @since 2022/8/29
     */
    private AddressBook getAddressBook(Long addressBookId) {
       return addressBookService.getById(addressBookId);
    }
}
